package com.beone.admin.security.handler;

import com.alibaba.fastjson.JSONObject;
import com.base.common.RequestContextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Title  在Spring默认的AccessDeniedHandler中只有对页面请求的处理，而没有对Ajax的处理。
 *          而在项目开发是Ajax又是我们要常用的技术，所以我们可以通过自定义AccessDeniedHandler来处理Ajax请求
 * @Author 覃忠君 on 2017/12/20.
 * @Copyright © 蜂投网
 */
public class AccessDeniedSupportAjaxHandler  implements AccessDeniedHandler{

    private static final Logger logger = LoggerFactory.getLogger(AccessDeniedSupportAjaxHandler.class);

    private String errorPage;
    /**
     * The error page to use. Must begin with a "/" and is interpreted relative to the current context root.
     *
     * @param errorPage the dispatcher path to display
     *
     * @throws IllegalArgumentException if the argument doesn't comply with the above limitations
     */
    public void setErrorPage(String errorPage) {
        if ((errorPage != null) && !errorPage.startsWith("/")) {
            throw new IllegalArgumentException("errorPage must begin with '/'");
        }
        this.errorPage = errorPage;
    }

    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException {
        logger.info("access denied url : {},  exception : {}", request.getRequestURL(), accessDeniedException.getMessage());
        boolean isAjax = RequestContextUtils.isAjaxRequest(request);
        if(isAjax){
            responseJSON(response);
        }else if (!response.isCommitted()) {
            if (errorPage != null) {
                // Put exception into request scope (perhaps of use to a view)
                request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
                // Set the 403 status code.
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                // forward to error page.
                RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
                dispatcher.forward(request, response);
            } else {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
            }
        }
    }

    /**
     * Ajax请求响应Json
     * @param response
     * @throws IOException
     */
    private void responseJSON(HttpServletResponse response)throws IOException{
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        JSONObject json = new JSONObject();
        json.put("errorCode",HttpServletResponse.SC_FORBIDDEN);
        json.put("errorMsg","权限不足!");
        PrintWriter writer = response.getWriter();
        writer.write(json.toJSONString());
        writer.flush();
    }
}
